Diese kleine Einleitung soll einerseits darauf aufmerksam machen, daß die Rubrik schon zum zweiten Mal dabei ist (seit Ausgabe 3).
Der MUI-Kurs erhält seine Fortsetzung durch einen Kursteil zum Einstieg in die Programmierung von Custom Classes. Der Ausstieg kommt in der nächsten Ausgabe. Zum vorigen und gleichzeitig ersten Kursteil folgt ein Nachruf in Form einer Ergänzung zur Einbindung der MUI-Includes in MaxonC++.
Wer schon immer mal wissen wollte, wie Programmierer es wohl schaffen, einen gräßlich langen Index in ihre Programmanleitungen zu schreiben, kann es in einem Artikel über TexInfo in der Softwarerubrik nachlesen.
Und dank Thomas Heinrich, der schon letztes Mal was zum AmZeiger beigetragen hat, gibt es noch einen Artikel über Memory Pools, die der Speicherfragmentierung entgegenwirken sollen.
Andererseits hat diese Einleitung noch eine andere Aufgabe, und jetzt gilt Euer Dank meinem Chefredakteur: ich sag' noch schnell, wie man Programme an verschiedene Sprachen anpaßt (lokalisiert).
GetCatalogStr(mycatalog,number,alt);.
Jau, das ist schon die wichtigste Funktion der locale.library. :-) Sie gibt einen Zeiger auf einen String zurück, und zwar auf den ggf. lokalisierten String. Alle Texte des Programms stehen in einem Katalog (mycatalog ist ein Zeiger darauf), und dessen Strings sind durchnumeriert (number). Ist eine Nummer nicht zu finden, muß ja trotzdem was im Fenster stehen. Daher gibt es noch die Möglichkeit, einen Zeiger auf einen Default- String zu übergeben (alt).
Da viele Programme ab OS 2.1 lokalisiert sind, aber auch noch unter OS 2.0 laufen sollen, bietet es sich an, eine eigene Funktion zu schreiben, die GetCatalogStr() nicht aufruft, wenn der Katalog nicht geöffnet werden konnte oder OS 2.0 vorliegt, sondern gleich den Default-String zurückgibt.
Bei mir sieht diese Funktion so aus:
char *LocStr( LONG number ) { static char undef[] = "#!!!"; char *r; if( mycatalog ) r = (char *) GetCatalogStr(mycatalog,number,undef); else r = CatCompArray[number].cca_Str; if( r ) { r++; return r; // Fall sollte eigentlich immer eintreten. } r = undef return ++r; }
Wozu nur dieses ominöse "r++"? Ich überspringe damit das erste Zeichen des Strings. Ich finde es nämlich recht praktisch, wenn ein Programm auch Tastaturkürzel (Shortcuts) versteht. Die müssen natürlich auch lokalisiert werden. Anstatt zwei Strings für jeden Text zu haben, schlage ich so zwei Fliegen mit einer Klappe.
Der Shortcut selbst läßt sich über diese Funktion auslesen:
char LocKey( LONG number ) { char *r; char k; if( mycatalog ) r = (char *) GetCatalogStr(mycatalog,number,NULL); else r = CatCompArray[number].cca_Str; if( r ) { k = *r; if( k == ' ' ) return '#'; return k; } return '#'; }
Die Raute ist also für den Fehlerfall (der nur bei einem Fehler des Programmierers eintritt) zuständig.
Naja, und wo wir gerade so schön bei MUI sind: die BubbleHelps sollen ja auch lokalisiert werden. Das mache ich zwar nicht im gleichen String, aber immer im String danach. Da es auch BubbleHelp für Flächen gibt (zu denen kein Text paßt), addiere ich nicht einfach nur 1 zur Stringnummer, sondern prüfe erst, ob der übergebene String mit einem @-Zeichen anfängt. So sind bei mir die BubbleHelps markiert. Wie wär's mit
char *LocHelp( LONG number ) { static char null[] = ""; char *r; for( short i=0; i<2; i++ ) { if( mycatalog ) r = (char *) GetCatalogStr(mycatalog, number+i, "undefined"); else r = CatCompArray[number+i].cca_Str; if( r ) { if( *r == '@' ) { r++; return r; } } } return null; }
Also läßt sich jetzt eine Stringnummer (für ein Gadget) angeben, auf die eine Stringnummer mit BubbleHelp folgt. Außerdem kann eine Stringnummer direkt die BubbleHelp bezeichnen, dann wird nicht weitergesprungen.
Wie kommt man nun an den "mycatalog"?
mycatalog = NULL; if( LocaleBase=OpenLibrary("locale.library",38) ) { if( loc = OpenLocale( NULL ) ) { // z.B. "madhouse.catalog" mycatalog=OpenCatalog(loc,CatalogName,OC_Version,27, TAG_DONE); // Version des Katalogs, in der #?.ct-Datei /\ anzugeben. } }
Und so wird er wieder am Programmende freigegeben:
if( LocaleBase ) { if( loc ) { if( mycatalog ) CloseCatalog( mycatalog ); CloseLocale( loc ) } CloseLibrary( LocaleBase ); }
Dann muß nur noch die #?.catalog-Datei erstellt werden. Das macht man am besten mit CatComp von Commodore (z.B. auf der Geek Gadgets 2). Das CatComp erlaubt auch die Ausgabe von C-Quelltext, der das Array mit der eingebauten Sprache (oben CatCompArray genannt) erzeugen kann.
Wichtig bei meiner recht spartanischen (aber meiner Meinung nach praktischen) Lösung ist es, daß auch wirklich der erste String die Nummer 0 erhält und fortlaufend durchnumeriert wird.
Jupp, das war jetzt wirklich der Schnelldurchlauf, noch dazu in letzter Minute (morgen ist Redaktionsschluß). Vielleicht sind auch Programmierer an meiner Lösung interessiert, die sich schon mal mit Locale beschäftigt haben.
Viel Fun und Erfolg mit der Coder's Corner wünscht Euch
Carsten Jahn
Coder's Corner-Redakteur
![]() |
Inhaltsverzeichnis | ![]() |
©`98Der AmZeiger |